package com.lry.basic.jvm.asm.transform_class.demo20;

import aj.org.objectweb.asm.ClassWriter;
import aj.org.objectweb.asm.MethodVisitor;
import com.lry.basic.jvm.asm.proxy.MethodInterceptor;
import com.lry.basic.jvm.asm.proxy.MyClassLoader;
import com.lry.basic.jvm.asm.utils.FileUtils;

import java.lang.reflect.Method;

import static aj.org.objectweb.asm.Opcodes.*;

public class HelloWorldGenerateCore {

//    public static void main(String[] args) throws Exception {
//        String relative_path = "com/lry/basic/jvm/asm/transform_class/demo20/CalPointsImpl.class";
//        String filepath = FileUtils.getFilePath(relative_path);
//
//        // (1) 生成byte[]内容
//        byte[] bytes = dump();
//
//        // (2) 保存byte[]到文件
//        FileUtils.writeBytes(filepath, bytes);
//
//        Class clazz = Class.forName("com.lry.basic.jvm.asm.transform_class.demo20.CalPointsImpl");
//
//        Object obj = clazz.newInstance();
//        Method method = clazz.getDeclaredMethod("calPoints",long.class);
//
//        System.out.println(method.invoke(obj, 1));
//
//    }

    public static void main(String[] args) throws Exception {
        byte[] bytes = dump();
        Class<?> clazz = new MyClassLoader().defineClassForName("com.lry.basic.jvm.asm.transform_class.demo20.CalPointsImpl", bytes);
        Object obj = clazz.newInstance();
        Method method = clazz.getDeclaredMethod("calPoints",long.class);
        System.out.println(method.invoke(obj, 1));
    }

    public static byte[] dump() throws Exception {
        // (1) 创建ClassWriter对象
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);

        // (2) 调用visitXxx()方法
        cw.visit(V1_8,ACC_PUBLIC,
                "com/lry/basic/jvm/asm/transform_class/demo20/CalPointsImpl",
                null,"java/lang/Object",
                new String[]{"com/lry/basic/jvm/asm/transform_class/demo20/CalPoints"});

        {
            MethodVisitor mv1 = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
            mv1.visitCode();
            mv1.visitVarInsn(ALOAD, 0);
            mv1.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
            mv1.visitInsn(RETURN);
            mv1.visitMaxs(0, 0);
            mv1.visitEnd();
        }

        {
            //points=points*2;

            MethodVisitor mv2 = cw.visitMethod(ACC_PUBLIC, "calPoints", "(J)J", null, null);
            mv2.visitCode();

            mv2.visitVarInsn(LLOAD,1);

            mv2.visitLdcInsn(2L);
            mv2.visitInsn(LMUL);

            mv2.visitVarInsn(LSTORE,1);
            mv2.visitVarInsn(LLOAD,1);
            mv2.visitInsn(LRETURN);
            mv2.visitMaxs(0, 0);
            mv2.visitEnd();
        }

        cw.visitEnd();

        // (3) 调用toByteArray()方法
        return cw.toByteArray();
    }
}
